import {Component, OnInit} from '@angular/core';
import {UserFormInfo} from './UserFormInfo';
import {ValidateUserInput} from './ValidateUserInput';
import {UserRegisterHTTPService} from './UserRegisterHTTPService';
import {UserRegisterMessage} from "./UserRegisterMessage";
import {Utils} from "../services/Utils";

@Component({
    selector: 'my-app',
    templateUrl: './userRegisterTemp.html',
    styleUrls:['./style-source/userRegister.scss']
})
export class UserRegisterComponent implements OnInit {
    // private verificationCodeImg:any = new Image();
    private verificationResult:string;

    private allInputFlag:any = {
        usernameFlag: "username",
        passwordFlag: "password",
        confirmFlag: "confirm",
        phoneFlag: "phone",
        phoneVerificationCodeFlag: "phoneVerificationCode",
        verificationCodeFlag: "verificationCode",
        clauseFlag: "clause"
    };

    public inputContent:any = {
        username: "",
        password: "",
        confirm: "",
        phone: "",
        phoneVerificationCode: "",
        verificationCode: "",
        clause: false
    };

    public formInputHidden:any = {
        hiddenUsernameHint: true,
        hiddenPasswordHint: true,
        hiddenConfirmHint: true,
        hiddenPhoneHint: true,
        hiddenPhoneVerificationCodeHint: true,
        hiddenVerificationCodeHint: true
    };

    public errorMessages:any = {
        usernameError: "",
        passwordError: "",
        confirmError: "",
        phoneError: "",
        phoneVerificationCodeError: "",
        verificationCodeError: "",
        clauseError: ""
    };

    public usernameSucceed:boolean = false;
    public usernameDefeat:boolean = false;
    public passwordSucceed:boolean = false;
    public passwordDefeat:boolean = false;
    public confirmSucceed:boolean = false;
    public confirmDefeat:boolean = false;
    public phoneSucceed:boolean = false;
    public phoneDefeat:boolean = false;
    public phoneVerificationCodeSucceed:boolean = false;
    public phoneVerificationCodeDefeat:boolean = false;
    public verificationCodeSucceed:boolean = false;
    public verificationCodeDefeat:boolean = false;

    constructor(private _userHTTPService:UserRegisterHTTPService) {
    }

    ngOnInit() {
        this.onloadVerificationImage();
    }

    private onloadVerificationImage():void {
        let verificationCodeImg:any = document.getElementById("verificationCodeImg");
        verificationCodeImg.onload = () => {
            this._userHTTPService.obtainVerificationResultInServer(serverResult => this.verificationResult = serverResult.result, error=> this.obtainServerResultError())
        };
        verificationCodeImg.src = "/register/obtainAuthImage.do?random=" + Math.random() * new Date().getMilliseconds();
    }

    private obtainServerResultError() {
        this.setResponseMessage(this.allInputFlag.verificationCodeFlag, "获得验证码失败，请点击重试", false);
    }

    /**
     * when username input box gained the focus, will invoke this method.
     */
    checkUsernameFocus():void {
        this.hiddenHintOrNot(this.allInputFlag.usernameFlag, false);
    }

    /**
     * when username input box lost the focus, will invoke this method.
     * in this method, will check username's value validation. Then will
     * set username's error message if defeat, or will set username to succeed.
     * @param username
     */
    checkUsernameBlur(username:string):void {

        this.hiddenHintOrNot(this.allInputFlag.usernameFlag, true);
        this.realCheckUsername(username);
    }

    private realCheckUsername(username:string) {
        if (username === "") {
            this.clearAllMessage(this.allInputFlag.usernameFlag);
            return;
        }

        let message:UserRegisterMessage = ValidateUserInput.checkUsername(username);

        if (message.flag) {
            this._userHTTPService.checkUserNameInServer(username, serverResult => this.checkSucceedUsernameCallback(serverResult),
                errorMsg => this.checkErrorUsernameCallback(errorMsg));
        } else {
            this.setResponseMessage(this.allInputFlag.usernameFlag, message.message, message.flag);
        }
    }

    /**
     * when username input box took place key up event, will invoke this method.
     * this method's main target is to clear all message if username input box is empty.
     */
    checkUsernameKeyUp():void {
        this.clearAllMessage(this.allInputFlag.usernameFlag);
    }

    private checkSucceedUsernameCallback(serverResult:any):void {
        let resultStr = serverResult.result, flag:boolean, message:string;

        if (resultStr === "defeat") {
            flag = false;
            message = "用户名已存在";
        } else {
            flag = true;
            message = "";
        }
        this.setResponseMessage(this.allInputFlag.usernameFlag, message, flag);
    }

    private checkErrorUsernameCallback(error:string):void {
        console.log(error);
        this.setResponseMessage(this.allInputFlag.usernameFlag, "服务器错误，请清除用户名并重新输入", false);
    }

    checkPasswordFocus():void {
        this.hiddenHintOrNot(this.allInputFlag.passwordFlag, false);
    }

    checkPasswordBlur(password:string):void {
        this.hiddenHintOrNot(this.allInputFlag.passwordFlag, true);
        this.realCheckPassword(password);
    }

    checkPasswordKeyUp(password:string):void {
        this.realCheckPassword(password);
    }

    /**
     * when password input has took place key event or blur event will invoke this method to check
     * whether password's value is legal or not.
     * note: after checking password's legality, should check confirm input as well.
     * @param password
     */
    private realCheckPassword(password:string):void {
        if (password !== "") {
            let message:UserRegisterMessage = ValidateUserInput.checkPassword(password);
            this.setResponseMessage(this.allInputFlag.passwordFlag, message.message, message.flag);
            this.checkConfirmForPassword();
        } else {
            this.clearAllMessage(this.allInputFlag.passwordFlag);
        }
    }

    checkConfirmFocus():void {
        this.hiddenHintOrNot(this.allInputFlag.confirmFlag, false);
    }

    checkConfirmBlur():void {
        this.hiddenHintOrNot(this.allInputFlag.confirmFlag, true);
        this.checkConfirmForPassword();
    }

    checkConfirmKeyUp():void {
        this.checkConfirmForPassword();
    }

    /**
     * check whether confirm's value is equal with password's value.
     */
    private checkConfirmForPassword() {
        if (this.inputContent.confirm !== "") {
            let message:UserRegisterMessage = ValidateUserInput.checkConfirm(this.inputContent.confirm, this.inputContent.password);
            this.setResponseMessage(this.allInputFlag.confirmFlag, message.message, message.flag);
        } else {
            this.clearAllMessage(this.allInputFlag.confirmFlag);
        }
    }

    checkPhoneFocus():void {
        this.hiddenHintOrNot(this.allInputFlag.phoneFlag, false);
    }

    checkPhoneBlur(phone:string):void {
        this.hiddenHintOrNot(this.allInputFlag.phoneFlag, true);
        this.realCheckPhone(phone);
    }

    checkPhoneKeyUp(phone:string):void {
        this.realCheckPhone(phone);
    }

    private realCheckPhone(phone:string):void {
        if (phone === "") {
            this.clearAllMessage(this.allInputFlag.phoneFlag);
        } else {
            let resultMessage = ValidateUserInput.checkPhone(phone);
            this.setResponseMessage(this.allInputFlag.phoneFlag, resultMessage.message, resultMessage.flag);
        }
    }

    checkPhoneVerificationCodeFocus():void {
        this.hiddenHintOrNot(this.allInputFlag.phoneVerificationCodeFlag, false);
    }

    checkPhoneVerificationCodeBlur(phoneVerificationCode:string):void {
        this.hiddenHintOrNot(this.allInputFlag.phoneVerificationCodeFlag, true);
        this.realCheckPhoneVerificationCode(phoneVerificationCode);
    }

    checkPhoneVerificationCodeKeyUp(phoneVerificationCode:string):void {
        this.realCheckPhoneVerificationCode(phoneVerificationCode);
    }

    private realCheckPhoneVerificationCode(phoneVerificationCode:string):void {
        if (phoneVerificationCode === "") {
            this.clearAllMessage(this.allInputFlag.phoneVerificationCodeFlag);
        } else {
            let resultMessage:UserRegisterMessage = ValidateUserInput.checkPhoneVerificationCode(phoneVerificationCode);
            this.setResponseMessage(this.allInputFlag.phoneVerificationCodeFlag, resultMessage.message, resultMessage.flag);
        }
    }

    verificationCodeFocus():void {
        this.hiddenHintOrNot(this.allInputFlag.verificationCodeFlag, false);
    }

    verificationCodeBlur(verificationCode:string):void {
        this.hiddenHintOrNot(this.allInputFlag.verificationCodeFlag, true);
        this.realCheckVerificationCode(verificationCode);
    }

    verificationCodeKeyUp(verificationCode:string):void {
        this.realCheckVerificationCode(verificationCode);
    }

    private realCheckVerificationCode(verificationCode:string) {
        if (verificationCode === "") {
            this.clearAllMessage(this.allInputFlag.verificationCodeFlag);
        } else {
            let resultMessage:UserRegisterMessage = ValidateUserInput.checkVerificationCode(verificationCode, this.verificationResult);
            this.setResponseMessage(this.allInputFlag.verificationCodeFlag, resultMessage.message, resultMessage.flag);
        }
    }

    clauseChange():void {
        this.errorMessages.clauseError = "";
    }

    submitRegister():void {
        let isEmptyResult:boolean = this.checkAllInputHasEmpty();
        if (!isEmptyResult && this.checkAllInputIsCorrect()) {
            this._userHTTPService.sendUserRegisterInfo2Server(new UserFormInfo(this.inputContent.username, this.inputContent.password, this.inputContent.phone))
        }
    }

    private checkAllInputHasEmpty():boolean {
        let flag:boolean = false;
        for (let target in this.inputContent) {
            if (this.inputContent.hasOwnProperty(target)) {
                if (this.inputContent[target] === "") {
                    this.setResponseMessage(target, "该选项为必填项，请输入相应信息", false);
                    flag = true;
                    break;
                }
            }
        }
        if (!flag) {
            if (!this.inputContent.clause) {
                this.errorMessages.clauseError = "请仔细阅读条款并确认";
                flag = !this.inputContent.clause;
            }
        }
        return flag;
    }

    private checkAllInputIsCorrect():boolean {
        this.realCheckUsername(this.inputContent.username);
        this.realCheckPassword(this.inputContent.password);
        this.realCheckPhone(this.inputContent.phone);
        this.realCheckPhoneVerificationCode(this.inputContent.phoneVerificationCode);
        this.realCheckVerificationCode(this.inputContent.verificationCode);
        return this.usernameSucceed && this.passwordSucceed && this.confirmSucceed && this.phoneSucceed
            && this.phoneVerificationCodeSucceed && this.verificationCodeSucceed;
    }

    /**
     * depend on verified result to set corresponding message and input box's border.
     * @param target the input box object that is checked.
     * @param message should be displayed message
     * @param succeedOrNot if verified result is successful will be true, otherwise will be false.
     */
    private setResponseMessage(target:string, message:string, succeedOrNot:boolean):void {
        this[target + "Defeat"] = !(this[target + "Succeed"] = succeedOrNot);
        this.errorMessages[target + "Error"] = message;
    }

    /**
     * clear all message, either error message or target input box's border.
     * @param target the input box's name label.
     */
    private clearAllMessage(target:string):void {
        this[target + "Defeat"] = this[target + "Succeed"] = false;
        this.errorMessages[target + "Error"] = "";
    }

    /**
     * show or hidden target input box's hint message.
     * @param target
     * @param flag
     */
    private hiddenHintOrNot(target:string, flag:boolean):void {
        target = Utils.setInitialUpperCase(target);
        this.formInputHidden["hidden" + target + "Hint"] = flag;
    }
}
